home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / mips-sgi-irix6.2 / rcs2log.z / rcs2log
Encoding:
Text File  |  1998-05-21  |  16.7 KB  |  651 lines

  1. #! /bin/sh
  2.  
  3. # RCS to ChangeLog generator
  4.  
  5. # Generate a change log prefix from RCS files (perhaps in the CVS repository)
  6. # and the ChangeLog (if any).
  7. # Output the new prefix to standard output.
  8. # You can edit this prefix by hand, and then prepend it to ChangeLog.
  9.  
  10. # Ignore log entries that start with `#'.
  11. # Clump together log entries that start with `{topic} ',
  12. # where `topic' contains neither white space nor `}'.
  13.  
  14. Help='The default FILEs are the files registered under the working directory.
  15. Options:
  16.  
  17.   -c CHANGELOG  Output a change log prefix to CHANGELOG (default ChangeLog).
  18.   -h HOSTNAME  Use HOSTNAME in change log entries (default current host).
  19.   -i INDENT  Indent change log lines by INDENT spaces (default 8).
  20.   -l LENGTH  Try to limit log lines to LENGTH characters (default 79).
  21.   -R  If no FILEs are given and RCS is used, recurse through working directory.
  22.   -r OPTION  Pass OPTION to subsidiary log command.
  23.   -t TABWIDTH  Tab stops are every TABWIDTH characters (default 8).
  24.   -u "LOGIN<tab>FULLNAME<tab>MAILADDR"  Assume LOGIN has FULLNAME and MAILADDR.
  25.   -v  Append RCS revision to file names in log lines.
  26.   --help  Output help.
  27.   --version  Output version number.
  28.  
  29. Report bugs to <bug-gnu-emacs@prep.ai.mit.edu>.'
  30.  
  31. Id='$Id: rcs2log,v 1.37 1997/03/21 22:19:30 eggert Exp $'
  32.  
  33. # Copyright 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
  34.  
  35. # This program is free software; you can redistribute it and/or modify
  36. # it under the terms of the GNU General Public License as published by
  37. # the Free Software Foundation; either version 2, or (at your option)
  38. # any later version.
  39. #
  40. # This program is distributed in the hope that it will be useful,
  41. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  42. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  43. # GNU General Public License for more details.
  44. #
  45. # You should have received a copy of the GNU General Public License
  46. # along with this program; see the file COPYING.  If not, write to the
  47. # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  48. # Boston, MA 02111-1307, USA.
  49.  
  50. Copyright='Copyright 1997 Free Software Foundation, Inc.
  51. This program comes with NO WARRANTY, to the extent permitted by law.
  52. You may redistribute copies of this program
  53. under the terms of the GNU General Public License.
  54. For more information about these matters, see the files named COPYING.
  55. Author: Paul Eggert <eggert@twinsun.com>'
  56.  
  57. tab='    '
  58. nl='
  59. '
  60.  
  61. # Parse options.
  62.  
  63. # defaults
  64. : ${AWK=awk}
  65. : ${TMPDIR=/tmp}
  66. changelog=ChangeLog # change log file name
  67. datearg= # rlog date option
  68. hostname= # name of local host (if empty, will deduce it later)
  69. indent=8 # indent of log line
  70. length=79 # suggested max width of log line
  71. logins= # login names for people we know fullnames and mailaddrs of
  72. loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets
  73. logTZ= # time zone for log dates (if empty, use local time)
  74. recursive= # t if we want recursive rlog
  75. revision= # t if we want revision numbers
  76. rlog_options= # options to pass to rlog
  77. tabwidth=8 # width of horizontal tab
  78.  
  79. while :
  80. do
  81.     case $1 in
  82.     -c)    changelog=${2?}; shift;;
  83.     -i)    indent=${2?}; shift;;
  84.     -h)    hostname=${2?}; shift;;
  85.     -l)    length=${2?}; shift;;
  86.     -[nu])    # -n is obsolescent; it is replaced by -u.
  87.         case $1 in
  88.         -n)    case ${2?}${3?}${4?} in
  89.             *"$tab"* | *"$nl"*)
  90.                 echo >&2 "$0: -n '$2' '$3' '$4': tabs, newlines not allowed"
  91.                 exit 1
  92.             esac
  93.             loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2$tab$3$tab$4
  94.             shift; shift; shift;;
  95.         -u)
  96.             # If $2 is not tab-separated, use colon for separator.
  97.             case ${2?} in
  98.             *"$nl"*)
  99.                 echo >&2 "$0: -u '$2': newlines not allowed"
  100.                 exit 1;;
  101.             *"$tab"*)
  102.                 t=$tab;;
  103.             *)
  104.                 t=:
  105.             esac
  106.             case $2 in
  107.             *"$t"*"$t"*"$t"*)
  108.                 echo >&2 "$0: -u '$2': too many fields"
  109.                 exit 1;;
  110.             *"$t"*"$t"*)
  111.                 ;;
  112.             *)
  113.                 echo >&2 "$0: -u '$2': not enough fields"
  114.                 exit 1
  115.             esac
  116.             loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2
  117.             shift
  118.         esac
  119.         logins=$logins$nl$login
  120.         ;;
  121.     -r)    rlog_options=$rlog_options$nl${2?}; shift;;
  122.     -R)    recursive=t;;
  123.     -t)    tabwidth=${2?}; shift;;
  124.     -v)    revision=t;;
  125.     --version)
  126.         set $Id
  127.         rcs2logVersion=$3
  128.         echo >&2 "rcs2log (GNU Emacs) $rcs2logVersion$nl$Copyright"
  129.         exit 0;;
  130.     -*)    echo >&2 "Usage: $0 [OPTION]... [FILE ...]$nl$Help"
  131.         case $1 in
  132.         --help) exit 0;;
  133.         *) exit 1
  134.         esac;;
  135.     *)    break
  136.     esac
  137.     shift
  138. done
  139.  
  140. month_data='
  141.     m[0]="Jan"; m[1]="Feb"; m[2]="Mar"
  142.     m[3]="Apr"; m[4]="May"; m[5]="Jun"
  143.     m[6]="Jul"; m[7]="Aug"; m[8]="Sep"
  144.     m[9]="Oct"; m[10]="Nov"; m[11]="Dec"
  145. '
  146.  
  147.  
  148. # Put rlog output into $rlogout.
  149.  
  150. # If no rlog options are given,
  151. # log the revisions checked in since the first ChangeLog entry.
  152. # Since ChangeLog is only by date, some of these revisions may be duplicates of
  153. # what's already in ChangeLog; it's the user's responsibility to remove them.
  154. case $rlog_options in
  155. '')
  156.     if test -s "$changelog"
  157.     then
  158.         e='
  159.             /^[0-9]+-[0-9][0-9]-[0-9][0-9]/{
  160.                 # ISO 8601 date
  161.                 print $1
  162.                 exit
  163.             }
  164.             /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{
  165.                 # old-fashioned date and time (Emacs 19.31 and earlier)
  166.                 '"$month_data"'
  167.                 year = $5
  168.                 for (i=0; i<=11; i++) if (m[i] == $2) break
  169.                 dd = $3
  170.                 printf "%d-%02d-%02d\n", year, i+1, dd
  171.                 exit
  172.             }
  173.         '
  174.         d=`$AWK "$e" <"$changelog"` || exit
  175.         case $d in
  176.         ?*) datearg="-d>$d"
  177.         esac
  178.     fi
  179. esac
  180.  
  181. # Use TZ specified by ChangeLog local variable, if any.
  182. if test -s "$changelog"
  183. then
  184.     extractTZ='
  185.         /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*"\([^"]*\)".*/{
  186.             s//\1/; p; q
  187.         }
  188.         /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*t.*/{
  189.             s//UTC0/; p; q
  190.         }
  191.     '
  192.     logTZ=`tail "$changelog" | sed -n "$extractTZ"`
  193.     case $logTZ in
  194.     ?*) TZ=$logTZ; export TZ
  195.     esac
  196. fi
  197.  
  198. # If CVS is in use, examine its repository, not the normal RCS files.
  199. if test ! -f CVS/Repository
  200. then
  201.     rlog=rlog
  202.     repository=
  203. else
  204.     rlog='cvs -q log'
  205.     repository=`sed 1q <CVS/Repository` || exit
  206.     test ! -f CVS/Root || CVSROOT=`cat <CVS/Root` || exit
  207.     case $CVSROOT in
  208.     *:/*)
  209.         # remote repository
  210.         ;;
  211.     *)
  212.         # local repository
  213.         case $repository in
  214.         /*) ;;
  215.         *) repository=${CVSROOT?}/$repository
  216.         esac
  217.         if test ! -d "$repository"
  218.         then
  219.             echo >&2 "$0: $repository: bad repository (see CVS/Repository)"
  220.             exit 1
  221.         fi
  222.     esac
  223. fi
  224.  
  225. # Use $rlog's -zLT option, if $rlog supports it.
  226. case `$rlog -zLT 2>&1` in
  227. *' option'*) ;;
  228. *) rlog_options=-zLT$nl$rlog_options
  229. esac
  230.  
  231. # With no arguments, examine all files under the RCS directory.
  232. case $# in
  233. 0)
  234.     case $repository in
  235.     '')
  236.         oldIFS=$IFS
  237.         IFS=$nl
  238.         case $recursive in
  239.         t)
  240.             RCSdirs=`find . -name RCS -type d -print`
  241.             filesFromRCSfiles='s|,v$||; s|/RCS/|/|; s|^\./||'
  242.             files=`
  243.                 {
  244.                     case $RCSdirs in
  245.                     ?*) find $RCSdirs \
  246.                             -type f \
  247.                             ! -name '*_' \
  248.                             ! -name ',*,' \
  249.                             ! -name '.*_' \
  250.                             ! -name .rcsfreeze.log \
  251.                             ! -name .rcsfreeze.ver \
  252.                             -print
  253.                     esac
  254.                     find . -name '*,v' -print
  255.                 } |
  256.                 sort -u |
  257.                 sed "$filesFromRCSfiles"
  258.             `;;
  259.         *)
  260.             files=
  261.             for file in RCS/.* RCS/* .*,v *,v
  262.             do
  263.                 case $file in
  264.                 RCS/. | RCS/.. | RCS/,*, | RCS/*_) continue;;
  265.                 RCS/.rcsfreeze.log | RCS/.rcsfreeze.ver) continue;;
  266.                 RCS/.\* | RCS/\* | .\*,v | \*,v) test -f "$file" || continue
  267.                 esac
  268.                 files=$files$nl$file
  269.             done
  270.             case $files in
  271.             '') exit 0
  272.             esac
  273.         esac
  274.         set x $files
  275.         shift
  276.         IFS=$oldIFS
  277.     esac
  278. esac
  279.  
  280. llogout=$TMPDIR/rcs2log$$l
  281. rlogout=$TMPDIR/rcs2log$$r
  282. trap exit 1 2 13 15
  283. trap "rm -f $llogout $rlogout; exit 1" 0
  284.  
  285. case $datearg in
  286. ?*) $rlog $rlog_options "$datearg" ${1+"$@"} >$rlogout;;
  287. '') $rlog $rlog_options ${1+"$@"} >$rlogout
  288. esac || exit
  289.  
  290.  
  291. # Get the full name of each author the logs mention, and set initialize_fullname
  292. # to awk code that initializes the `fullname' awk associative array.
  293. # Warning: foreign authors (i.e. not known in the passwd file) are mishandled;
  294. # you have to fix the resulting output by hand.
  295.  
  296. initialize_fullname=
  297. initialize_mailaddr=
  298.  
  299. case $loginFullnameMailaddrs in
  300. ?*)
  301.     case $loginFullnameMailaddrs in
  302.     *\"* | *\\*)
  303.         sed 's/["\\]/\\&/g' >$llogout <<EOF || exit
  304. $loginFullnameMailaddrs
  305. EOF
  306.         loginFullnameMailaddrs=`cat $llogout`
  307.     esac
  308.  
  309.     oldIFS=$IFS
  310.     IFS=$nl
  311.     for loginFullnameMailaddr in $loginFullnameMailaddrs
  312.     do
  313.         case $loginFullnameMailaddr in
  314.         *"$tab"*) IFS=$tab;;
  315.         *) IFS=:
  316.         esac
  317.         set x $loginFullnameMailaddr
  318.         login=$2
  319.         fullname=$3
  320.         mailaddr=$4
  321.         initialize_fullname="$initialize_fullname
  322.             fullname[\"$login\"] = \"$fullname\""
  323.         initialize_mailaddr="$initialize_mailaddr
  324.             mailaddr[\"$login\"] = \"$mailaddr\""
  325.     done
  326.     IFS=$oldIFS
  327. esac
  328.  
  329. case $llogout in
  330. ?*) sort -u -o $llogout <<EOF || exit
  331. $logins
  332. EOF
  333. esac
  334. output_authors='/^date: / {
  335.     if ($2 ~ /^[0-9]*[-\/][0-9][0-9][-\/][0-9][0-9]$/ && $3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][-+0-9:]*;$/ && $4 == "author:" && $5 ~ /^[^;]*;$/) {
  336.         print substr($5, 1, length($5)-1)
  337.     }
  338. }'
  339. authors=`
  340.     $AWK "$output_authors" <$rlogout |
  341.     case $llogout in
  342.     '') sort -u;;
  343.     ?*) sort -u | comm -23 - $llogout
  344.     esac
  345. `
  346. case $authors in
  347. ?*)
  348.     cat >$llogout <<EOF || exit
  349. $authors
  350. EOF
  351.     initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/'
  352.     initialize_author=`sed -e "$initialize_author_script" <$llogout`
  353.     awkscript='
  354.         BEGIN {
  355.             alphabet = "abcdefghijklmnopqrstuvwxyz"
  356.             ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  357.             '"$initialize_author"'
  358.         }
  359.         {
  360.             if (author[$1]) {
  361.                 fullname = $5
  362.                 if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) {
  363.                     # Remove the junk from fullnames like "0000-Admin(0000)".
  364.                     fullname = substr(fullname, index(fullname, "-") + 1)
  365.                     fullname = substr(fullname, 1, index(fullname, "(") - 1)
  366.                 }
  367.                 if (fullname ~ /,[^ ]/) {
  368.                     # Some sites put comma-separated junk after the fullname.
  369.                     # Remove it, but leave "Bill Gates, Jr" alone.
  370.                     fullname = substr(fullname, 1, index(fullname, ",") - 1)
  371.                 }
  372.                 abbr = index(fullname, "&")
  373.                 if (abbr) {
  374.                     a = substr($1, 1, 1)
  375.                     A = a
  376.                     i = index(alphabet, a)
  377.                     if (i) A = substr(ALPHABET, i, 1)
  378.                     fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1)
  379.                 }
  380.  
  381.                 # Quote quotes and backslashes properly in full names.
  382.                 # Do not use gsub; traditional awk lacks it.
  383.                 quoted = ""
  384.                 rest = fullname
  385.                 for (;;) {
  386.                     p = index(rest, "\\")
  387.                     q = index(rest, "\"")
  388.                     if (p) {
  389.                         if (q && q<p) p = q
  390.                     } else {
  391.                         if (!q) break
  392.                         p = q
  393.                     }
  394.                     quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1)
  395.                     rest = substr(rest, p+1)
  396.                 }
  397.  
  398.                 printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest
  399.                 author[$1] = 0
  400.             }
  401.         }
  402.     '
  403.  
  404.     initialize_fullname=`
  405.         (
  406.             cat /etc/passwd
  407.             for author in $authors
  408.             do nismatch $author passwd.org_dir
  409.             done
  410.             ypmatch $authors passwd
  411.         ) 2>/dev/null |
  412.         $AWK -F: "$awkscript"
  413.     `$initialize_fullname
  414. esac
  415.  
  416.  
  417. # Function to print a single log line.
  418. # We don't use awk functions, to stay compatible with old awk versions.
  419. # `Log' is the log message (with \n replaced by \r).
  420. # `files' contains the affected files.
  421. printlogline='{
  422.  
  423.     # Following the GNU coding standards, rewrite
  424.     #    * file: (function): comment
  425.     # to
  426.     #    * file (function): comment
  427.     if (Log ~ /^\([^)]*\): /) {
  428.         i = index(Log, ")")
  429.         files = files " " substr(Log, 1, i)
  430.         Log = substr(Log, i+3)
  431.     }
  432.  
  433.     # If "label: comment" is too long, break the line after the ":".
  434.     sep = " "
  435.     if ('"$length"' <= '"$indent"' + 1 + length(files) + index(Log, CR)) sep = "\n" indent_string
  436.  
  437.     # Print the label.
  438.     printf "%s*%s:", indent_string, files
  439.  
  440.     # Print each line of the log, transliterating \r to \n.
  441.     while ((i = index(Log, CR)) != 0) {
  442.         logline = substr(Log, 1, i-1)
  443.         if (logline ~ /[^'"$tab"' ]/) {
  444.             printf "%s%s\n", sep, logline
  445.         } else {
  446.             print ""
  447.         }
  448.         sep = indent_string
  449.         Log = substr(Log, i+1)
  450.     }
  451. }'
  452.  
  453. # Pattern to match the `revision' line of rlog output.
  454. rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$'
  455.  
  456. case $hostname in
  457. '')
  458.     hostname=`(
  459.         hostname || uname -n || uuname -l || cat /etc/whoami
  460.     ) 2>/dev/null` || {
  461.         echo >&2 "$0: cannot deduce hostname"
  462.         exit 1
  463.     }
  464.  
  465.     case $hostname in
  466.     *.*) ;;
  467.     *)
  468.         domainname=`(domainname) 2>/dev/null` &&
  469.         case $domainname in
  470.         *.*) hostname=$hostname.$domainname
  471.         esac
  472.     esac
  473. esac
  474.  
  475.  
  476. # Process the rlog output, generating ChangeLog style entries.
  477.  
  478. # First, reformat the rlog output so that each line contains one log entry.
  479. # Transliterate \n to \r so that multiline entries fit on a single line.
  480. # Discard irrelevant rlog output.
  481. $AWK <$rlogout '
  482.     BEGIN { repository = "'"$repository"'" }
  483.     /^RCS file:/ {
  484.         if (repository != "") {
  485.             filename = $3
  486.             if (substr(filename, 1, length(repository) + 1) == repository "/") {
  487.                 filename = substr(filename, length(repository) + 2)
  488.             }
  489.             if (filename ~ /,v$/) {
  490.                 filename = substr(filename, 1, length(filename) - 2)
  491.             }
  492.             if (filename ~ /(^|\/)Attic\/[^\/]*$/) {
  493.                 i = length(filename)
  494.                 while (substr(filename, i, 1) != "/") i--
  495.                 filename = substr(filename, 1, i - 6) substr(filename, i + 1)
  496.             }
  497.         }
  498.         rev = "?"
  499.     }
  500.     /^Working file:/ { if (repository == "") filename = $3 }
  501.     /'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ {
  502.         if ($0 ~ /'"$rlog_revision_pattern"'/) {
  503.             rev = $2
  504.             next
  505.         }
  506.         if ($0 ~ /^date: [0-9][- +\/0-9:]*;/) {
  507.             date = $2
  508.             if (date ~ /\//) {
  509.                 # This is a traditional RCS format date YYYY/MM/DD.
  510.                 # Replace "/"s with "-"s to get ISO format.
  511.                 newdate = ""
  512.                 while ((i = index(date, "/")) != 0) {
  513.                     newdate = newdate substr(date, 1, i-1) "-"
  514.                     date = substr(date, i+1)
  515.                 }
  516.                 date = newdate date
  517.             }
  518.             time = substr($3, 1, length($3) - 1)
  519.             author = substr($5, 1, length($5)-1)
  520.             printf "%s %s %s %s %s %c", filename, rev, date, time, author, 13
  521.             rev = "?"
  522.             next
  523.         }
  524.         if ($0 ~ /^branches: /) { next }
  525.         if ($0 ~ /^(-----------*|===========*)$/) { print ""; next }
  526.         if ($0 == "Initial revision" || $0 ~ /^file .+ was initially added on branch .+\.$/) {
  527.             $0 = "New file."
  528.         }
  529.         printf "%s%c", $0, 13
  530.     }
  531. ' |
  532.  
  533. # Now each line is of the form
  534. # FILENAME REVISION YYYY-MM-DD HH:MM:SS[+-TIMEZONE] AUTHOR \rLOG
  535. #    where \r stands for a carriage return,
  536. #    and each line of the log is terminated by \r instead of \n.
  537. # Sort the log entries, first by date+time (in reverse order),
  538. # then by author, then by log entry, and finally by file name and revision
  539. # (just in case).
  540. sort +2 -4r +4 +0 |
  541.  
  542. # Finally, reformat the sorted log entries.
  543. $AWK '
  544.     BEGIN {
  545.         logTZ = "'"$logTZ"'"
  546.         revision = "'"$revision"'"
  547.  
  548.         # Some awk variants do not understand "\r" or "\013", so we have to
  549.         # put a carriage return directly in the file.
  550.         CR="
  551. " # <-- There is a single CR between the " chars here.
  552.  
  553.         # Initialize the fullname and mailaddr associative arrays.
  554.         '"$initialize_fullname"'
  555.         '"$initialize_mailaddr"'
  556.  
  557.         # Initialize indent string.
  558.         indent_string = ""
  559.         i = '"$indent"'
  560.         if (0 < '"$tabwidth"')
  561.             for (;  '"$tabwidth"' <= i;  i -= '"$tabwidth"')
  562.                 indent_string = indent_string "\t"
  563.         while (1 <= i--)
  564.             indent_string = indent_string " "
  565.     }
  566.  
  567.     {
  568.         newlog = substr($0, 1 + index($0, CR))
  569.  
  570.         # Ignore log entries prefixed by "#".
  571.         if (newlog ~ /^#/) { next }
  572.  
  573.         if (Log != newlog || date != $3 || author != $5) {
  574.  
  575.             # The previous log and this log differ.
  576.  
  577.             # Print the old log.
  578.             if (date != "") '"$printlogline"'
  579.  
  580.             # Logs that begin with "{clumpname} " should be grouped together,
  581.             # and the clumpname should be removed.
  582.             # Extract the new clumpname from the log header,
  583.             # and use it to decide whether to output a blank line.
  584.             newclumpname = ""
  585.             sep = "\n"
  586.             if (date == "") sep = ""
  587.             if (newlog ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) {
  588.                 i = index(newlog, "}")
  589.                 newclumpname = substr(newlog, 1, i)
  590.                 while (substr(newlog, i+1) ~ /^['"$tab"' ]/) i++
  591.                 newlog = substr(newlog, i+1)
  592.                 if (clumpname == newclumpname) sep = ""
  593.             }
  594.             printf sep
  595.             clumpname = newclumpname
  596.  
  597.             # Get ready for the next log.
  598.             Log = newlog
  599.             if (files != "")
  600.                 for (i in filesknown)
  601.                     filesknown[i] = 0
  602.             files = ""
  603.         }
  604.         if (date != $3  ||  author != $5) {
  605.             # The previous date+author and this date+author differ.
  606.             # Print the new one.
  607.             date = $3
  608.             time = $4
  609.             author = $5
  610.  
  611.             zone = ""
  612.             if (logTZ && ((i = index(time, "-")) || (i = index(time, "+"))))
  613.                 zone = " " substr(time, i)
  614.  
  615.             # Print "date[ timezone]  fullname  <email address>".
  616.             # Get fullname and email address from associative arrays;
  617.             # default to author and author@hostname if not in arrays.
  618.             if (fullname[author])
  619.                 auth = fullname[author]
  620.             else
  621.                 auth = author
  622.             printf "%s%s  %s  ", date, zone, auth
  623.             if (mailaddr[author])
  624.                 printf "<%s>\n\n", mailaddr[author]
  625.             else
  626.                 printf "<%s@%s>\n\n", author, "'"$hostname"'"
  627.         }
  628.         if (! filesknown[$1]) {
  629.             filesknown[$1] = 1
  630.             if (files == "") files = " " $1
  631.             else files = files ", " $1
  632.             if (revision && $2 != "?") files = files " " $2
  633.         }
  634.     }
  635.     END {
  636.         # Print the last log.
  637.         if (date != "") {
  638.             '"$printlogline"'
  639.             printf "\n"
  640.         }
  641.     }
  642. ' &&
  643.  
  644.  
  645. # Exit successfully.
  646.  
  647. exec rm -f $llogout $rlogout
  648.  
  649. # Local Variables:
  650. # tab-width:4
  651. # End:
  652.